#include <iostream>
#include <vector>
#include "Performance.h"


using namespace std;

Performance* Performance::instant;

Performance* Performance::getInstant()
{
	if ( instant == NULL )
		instant = new Performance();
	return instant;
}

Module_Aurora* Performance::LoadModule ( char* spriteName )
{
	char lineOrigin[200], _temp[200];	
	char* line;
	int moduleCount = 0;
	Module_Aurora* module = new Module_Aurora[Util::getInstant()->getModuleMax(spriteName)];

	FILE *fIn = fopen( spriteName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << spriteName;
		return module;
	}

	while ( !feof ( fIn ) )
	{		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

		if ( line[0] == 'M' && line[1] == 'D' )
		{
			Module_Aurora _module;
			strcpy ( _module.moduleName, "0000");
			char moduleID[10];
			sscanf ( &line[0], "%s" "%s" "%s" "%s" "%d" "%d" "%d" "%d" "%s", &_temp, &moduleID, &_temp, &_temp, &_module.moduleSize.x, &_module.moduleSize.y, &_module.moduleSize.w, &_module.moduleSize.h, &_module.moduleName );
			
			int ID = Util::getInstant()->convertHexToDec( moduleID );

			module[ID].moduleSize.x = _module.moduleSize.x;
			module[ID].moduleSize.y = _module.moduleSize.y;
			module[ID].moduleSize.w = _module.moduleSize.w;
			module[ID].moduleSize.h = _module.moduleSize.h;
			module[ID].indexUpDown = moduleCount;
			//frame name image_frame_1
			char frameName[50];
			strcpy ( frameName, Util::getInstant()->getImageName( spriteName ) );
			strcat ( frameName, "_" );

			if ( _module.moduleName[0] == '0' && _module.moduleName[1] == '0' && _module.moduleName[2] == '0' && _module.moduleName[3] == '0')
			{
				strcat ( frameName, "frame_" );
				strcat ( frameName, Util::getInstant()->convertDecToChar( moduleCount ) );
			}
			else
			{
				for ( int i = 0; i < strlen ( _module.moduleName ) - 2; i++ )
					_module.moduleName[i] = _module.moduleName[i + 1];
				_module.moduleName[strlen ( _module.moduleName ) - 2] = '\0';		
				strcat ( frameName, "frame_" );
				strcat ( frameName, _module.moduleName );
			}

			//copy to 
			strcpy ( module[ID].moduleName, frameName );
			moduleCount++;
		}

		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );
		memset ( _temp, 0, sizeof ( _temp ) );
		memset ( _temp, 0, sizeof ( _temp ) );		

		if ( line[0] == '}' )
			break;
	}

	/*
	for ( int i = 0; i < Util::getInstant()->getModuleMax(spriteName); i++)
	{
		cout << module[i].moduleName << endl;
	}
	*/

	fclose ( fIn );
	return module;
}

Frame_Aurora* Performance::LoadFrame ( char* spriteName )
{
	char lineOrigin[200], _temp[200];	
	char* line;
	int frameCount = 0;
	
	Frame_Aurora* frame = new Frame_Aurora[Util::getInstant()->getFrameMax(spriteName)];

	FILE *fIn = fopen( spriteName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << spriteName;
		return frame;
	}

	while ( !feof ( fIn ) )
	{		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

		if ( line[0] == 'F' && line[1] == 'R' && line[2] == 'A' && line[3] == 'M' && line[4] == 'E' )
		{
			char frameID[10];
			char fmoduleID[10];
			memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
			fgets( lineOrigin, sizeof( lineOrigin ),fIn );
			line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

			//ID
			memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
			fgets( lineOrigin, sizeof( lineOrigin ),fIn );
			line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

			sscanf ( &line[0], "%s", &frameID );			
			int ID = Util::getInstant()->convertHexToDec( frameID );

			//fmodule
			memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
			fgets( lineOrigin, sizeof( lineOrigin ),fIn );
			line = Util::getInstant()->cutSpaceBefore ( lineOrigin );
			sscanf ( &line[0], "%s" "%s", &_temp, &fmoduleID );	
			frame[ID].fModuleID = Util::getInstant()->convertHexToDec( fmoduleID );
			frame[ID].indexUpDown = frameCount;
			frameCount++;
		}

		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );
		memset ( _temp, 0, sizeof ( _temp ) );
		memset ( _temp, 0, sizeof ( _temp ) );		

		if ( line[0] == 'A' && line[0] == 'N' && line[0] == 'I' && line[0] == 'M' )
			break;
	}

	/*
	for ( int i = 0; i < Util::getInstant()->getFrameMax(spriteName); i++)
	{
		cout << frame[i].fModuleID << endl;
	}
	*/

	fclose ( fIn );
	return frame;
}

Anim_Aurora* Performance::LoadAnim ( char* spriteName )
{
	char lineOrigin[200], _temp[200];	
	char* line;
	int isload = 0;
	int ID = 0; 	
	int aFrameCount = 0;
	int animCount = 0;
	
	Anim_Aurora* anim = new Anim_Aurora[Util::getInstant()->getAnimMax(spriteName)];

	FILE *fIn = fopen( spriteName, "r");
	if ( fIn == NULL )
	{
		cout << endl << "\nCan not read file: " << spriteName;
		return anim;
	}

	while ( !feof ( fIn ) )
	{		
		fgets( lineOrigin, sizeof( lineOrigin ),fIn );
		line = Util::getInstant()->cutSpaceBefore ( lineOrigin );

		if ( line[0] == 'A' && line[1] == 'N' && line[2] == 'I' && line[3] == 'M' || isload)
		{			
			int numAFrame = 0;		
			char animName[50];

			if ( !isload ) //start to get ID, nam, 
			{				
				strcpy ( line, Util::getInstant()->replaceChar ( line, '/', ' ' ) );
				strcpy ( line, Util::getInstant()->replaceChar ( line, '=', ' ' ) );
				strcpy ( line, Util::getInstant()->replaceChar ( line, ',', ' ' ) );				
				sscanf ( &line[0], "%s" "%s" "%s" "%d" "%s" "%d", &_temp, &animName, &_temp, &ID, &_temp, &numAFrame );
				
				anim[ID].aFrameID = new Frame_Aurora[numAFrame];
				anim[ID].numAframe = numAFrame;
				//name of anim
				for ( int i = 0; i < strlen ( animName ) - 2; i ++ )
					animName[i] = animName[i + 1];
				animName[strlen ( animName ) - 2] = '\0';

				strcpy ( anim[ID].animName, Util::getInstant()->getImageName( spriteName ) );
				strcat ( anim[ID].animName, "_" );
				if ( animName[0] == '\0')
				{
					strcat ( anim[ID].animName, "anim_");
					strcat ( anim[ID].animName, Util::getInstant()->convertDecToChar ( animCount ) );
				}
				else
				{
					strcat ( anim[ID].animName, "anim_" );
					strcat ( anim[ID].animName, animName );
				}

				isload = 1;
				aFrameCount = 0;
				animCount++;
			}
			else if ( line[0] == 'A' && line[1] == 'F' ) //get AFrame
			{
				int aframeID;
				Point pos;
				char offID[20];
				sscanf ( &line[0], "%s" "%s" "%s" "%d" "%d", &_temp, &offID, &_temp, &pos.x, &pos.y );				

				aframeID = Util::getInstant()->convertHexToDec ( offID );
				anim[ID].aFrameID[aFrameCount].fModuleID = aframeID;
				anim[ID].aFrameID[aFrameCount].position.x = pos.x;
				anim[ID].aFrameID[aFrameCount].position.y = pos.y;
				aFrameCount++;
				
			}

			if ( line[0] == '}' )
				isload = 0;
					
			
		}

		memset ( lineOrigin, 0, sizeof ( lineOrigin ) );
		memset ( line, 0, sizeof ( line ) );
		memset ( _temp, 0, sizeof ( _temp ) );
		memset ( _temp, 0, sizeof ( _temp ) );		
	}

	/*
	for ( int i = 0; i < Util::getInstant()->getAnimMax(spriteName); i++)
	{
		cout << anim[i].animName << endl;
	}	
	*/
	fclose ( fIn );
	return anim;
}

SpriteAurora* Performance::LoadSprite ( char * spriteName )
{
	SpriteAurora* sprite = new SpriteAurora( Util::getInstant()->getModuleMax(spriteName), Util::getInstant()->getFrameMax(spriteName), Util::getInstant()->getAnimMax(spriteName) );
	sprite->setImageName ( Util::getInstant()->getImageName ( spriteName ) );
	sprite->setImageExtendName ( Util::getInstant()->getImageNameWithExtent ( spriteName ) );
	sprite->setImageSize ( Util::getInstant()->getImageSize( spriteName ).x, Util::getInstant()->getImageSize( spriteName ).y );
	sprite->module = LoadModule (spriteName );
	sprite->frame = LoadFrame (spriteName );
	sprite->anim = LoadAnim (spriteName );
	return sprite;
}



SpriteAurora* Performance::LoadAllSprite ( char* spriteListFile )
{
	vector< SpriteAurora* > allSprite;
	SpriteAurora* _allSprite = NULL;
	if ( spriteListSuccess ( spriteListFile ) )
	{
		vector < Sprite_Export > spriteList = getSpriteList ( spriteListFile );
		{
			int imageLength = 0;
			for ( vector < Sprite_Export >::iterator i = spriteList.begin(); i != spriteList.end(); i++ )
			{
				SpriteAurora* sprite = LoadSprite ( (*i).spriteName );
				allSprite.push_back ( sprite );
			}
		}
		_allSprite = new SpriteAurora[allSprite.size()];
		int count = 0;
		for ( vector < SpriteAurora* >::iterator i = allSprite.begin(); i != allSprite.end(); i++ )
		{
			_allSprite[count].anim = (*i)->anim;
			_allSprite[count].frame = (*i)->frame;
			_allSprite[count].imageExtendName = (*i)->imageExtendName;
			_allSprite[count].imageName = (*i)->imageName;
			_allSprite[count].imageSize = (*i)->imageSize;
			_allSprite[count].module = (*i)->module;
			_allSprite[count].numOfAnim = (*i)->numOfAnim;
			_allSprite[count].numOfFrame = (*i)->numOfFrame;
			_allSprite[count++].numOfModule = (*i)->numOfModule;
		}
	}
	return _allSprite;
}

vector < Sprite_Export > Performance::getSpriteList ( char* spriteListFile )
{
	char spriteID[50], spriteName[50], spritePath[256], temp[10];
	char *line;
	int plistType = 0;	

	FILE* f = fopen ( spriteListFile, "r" );	
	vector < Sprite_Export > _spriteList;
	
	if ( f == NULL )
	{
		cout << "Can not read file: " << spriteListFile << endl;
		return _spriteList;
	}
	while ( !feof ( f ) )
	{
		fscanf ( f, "%s" "%s" "%s", &spriteID, &temp, &spritePath );

		if ( spriteID[0] == '\0' )
			continue;
		//spriteID
		for (int i = 0; i < strlen( spriteID ) - 2; i ++ )
			spriteID[i] = spriteID[i + 1];
		spriteID[ strlen( spriteID ) - 2 ] = '\0';

		//sprite name
		int i;
		for ( i = 0; i < strlen ( spritePath ) - 1; i ++ )
			spritePath[i] = spritePath[i + 1];
		spritePath[i-1] = '\0';			

		//push
		Sprite_Export sprite_ex;
		strcpy ( sprite_ex.spriteID, strupr(spriteID) );
		strcpy ( sprite_ex.spriteName, spritePath );
		sprite_ex.plistType = 0;
		if ( Util::getInstant()->isExist ( sprite_ex.spriteName ) )
			_spriteList.push_back ( sprite_ex );
		else
		{
			cout << endl << "Build sprite: " << sprite_ex.spriteName << "       -----ERROR------" << endl;
			if ( !Util::getInstant()->isExist ( sprite_ex.spriteName ) )
				cout << "Not exist sprite: " << sprite_ex.spriteName;			
		}

		memset ( spriteID, 0, sizeof (spriteID) );
		memset ( spriteName, 0, sizeof (spriteName) );
		memset ( spritePath, 0, sizeof (spritePath) );
	}

	return _spriteList;
}

int Performance::spriteListSuccess ( char* spriteListFile )
{
	char spriteID[50], spriteName[50], spritePath[256], temp[10];
	char *line;
	int plistType = 0, success = 1;

	FILE* f = fopen ( spriteListFile, "r" );	
	vector < Sprite_Export > _spriteList;
	
	if ( f == NULL )
	{
		cout << "Can not read file: " << spriteListFile << endl;
		return 0;
	}
	while ( !feof ( f ) )
	{
		fscanf ( f, "%s" "%s" "%s", &spriteID, &temp, &spritePath );

		if ( spriteID[0] == '\0' )
			continue;
		//spriteID
		for (int i = 0; i < strlen( spriteID ) - 2; i ++ )
			spriteID[i] = spriteID[i + 1];
		spriteID[ strlen( spriteID ) - 2 ] = '\0';

		//sprite name
		int i;
		for ( i = 0; i < strlen ( spritePath ) - 1; i ++ )
			spritePath[i] = spritePath[i + 1];
		spritePath[i-1] = '\0';		

		//push
		Sprite_Export sprite_ex;
		strcpy ( sprite_ex.spriteID, strupr(spriteID) );
		strcpy ( sprite_ex.spriteName, spritePath );
		sprite_ex.plistType = 0;
		if ( Util::getInstant()->isExist ( sprite_ex.spriteName ) )
			_spriteList.push_back ( sprite_ex );
		else
		{
			cout << endl << "Build sprite: " << sprite_ex.spriteName << "       -----ERROR------" << endl;
			if ( !Util::getInstant()->isExist ( sprite_ex.spriteName ) )
				cout << "Not exist sprite: " << sprite_ex.spriteName;			
			success  = 0;
		}

		memset ( spriteID, 0, sizeof (spriteID) );
		memset ( spriteName, 0, sizeof (spriteName) );
		memset ( spritePath, 0, sizeof (spritePath) );
	}

	return success;
}

int Performance::getModuleID( int spriteID, int frameIndexUpDown, SpriteAurora* spriteArray )
{	
	int frameID = 0;
	for ( int i = 0; i < spriteArray[spriteID].numOfFrame; i++ )
	{
		if ( frameIndexUpDown == spriteArray[spriteID].frame[i].indexUpDown )
		{
			frameID = i;
			break;
		}
	}
	int moduleID = spriteArray[spriteID].getModuleID( frameID );
	return spriteArray[spriteID].module[moduleID].indexUpDown;
}
